/*************************************************************************
 *
 *   file			: Message.cs
 *   author			: Thomas "zeroflag" Kraemer
 *   author email	: zeroflag@zeroflag.de
 *   copyright		: (C) 2006-2008  Thomas "zeroflag" Kraemer
 *   last changed	: $LastChangedDate: 2008-11-25 18:16:45 +0800 (Tue, 25 Nov 2008) $
 *   last author	: $LastChangedBy: dominikseifert $
 *   revision		: $Rev: 686 $
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 *   
 *   Modifications by Toby "tobz" Lawrence for WCell.
 *
 *************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace WCell.Util.Threading
{
	/// <summary>
	/// Defines a message with no input parameters.
	/// </summary>
	public class Message : IMessage
	{
		//private static LockfreeQueue<Message> msgPool;
		public static Message Obtain(Action callback)
		{
			// TODO: Object Pooling
			return new Message(callback);
		}

		/// <summary>
		/// Default constructor.
		/// </summary>
		public Message()
		{
		}

		/// <summary>
		/// Constructs a message with the specific callback.
		/// </summary>
		/// <param name="callback">the callback to invoke when the message is executed</param>
		public Message(Action callback)
		{
			Callback = callback;
		}

		/// <summary>
		/// The callback that is called when the message is executed.
		/// </summary>
		public Action Callback
		{
			get;
			private set;
		}

		/// <summary>
		/// Executes the message, calling any callbacks that are bound.
		/// </summary>
		public virtual void Execute()
		{
			Action cb = Callback;
			if (cb != null)
			{
				cb();
			}
		}

		public static implicit operator Message(Action dele)
		{
			return new Message(dele);
		}
	}


	/// <summary>
	/// Rather performance-hungry message to ensure that a task
	/// executed before continuing
	/// </summary>
	public class WaitMessage : Message
	{
		bool m_executed;

		public override void Execute()
		{
			try
			{
				base.Execute();
			}
			finally
			{
				lock (this)
				{
					m_executed = true;
					Monitor.PulseAll(this);
				}
			}
		}

		/// <summary>
		/// Waits until this Message executed.
		/// </summary>
		public void Wait()
		{
			if (!m_executed)
			{
				lock (this)
				{
					Monitor.Wait(this);
				}
			}
		}
	}
}
